﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System.Linq
{

    public delegate void IndexedAction<TValue, TIndex>(TValue value, TIndex index);
    public delegate TResualt IndexedSelector<TValue, TIndex, TResualt>(TValue value, TIndex index);
    static  public  class ArrayExtention
    {
        static public void ForEach<T>(this T[] array, int start, int repeatTime, int incSeed, IndexedAction<T, int> job)
        {
            if (start + (repeatTime - 1) * incSeed > array.Length || start + (repeatTime - 1) * incSeed < 0)
            {
                throw new System.ArgumentOutOfRangeException("start + (repeatTime - 1) * incSeed", "array is too sort to do this");
                
            }
 
            for (var i = 0; i < repeatTime; i++)
            {
                var tmp_index = incSeed * i + start;

                job(array[tmp_index], tmp_index);
            }
        
        }
        static public void ForEach<T>(this T[] array, int start, int repeatTime, IndexedAction<T,int> job)
        {
             ForEach(array, start, repeatTime, 1, job);
        }
        static public void ForEach<T>(this T[] array, IndexedAction<T, int> job)
        {
            ForEach(array, 0, array.Length , 1, job);
        }

        static public IEnumerable<TResualt> Select<T, TResualt>(this T[] array, int start, int repeatTime, int incSeed, IndexedSelector<T, int, TResualt> selector)
        {
            if (start + (repeatTime - 1) * incSeed > array.Length || start + (repeatTime - 1) * incSeed < 0)
            {
                throw new System.ArgumentOutOfRangeException("start + (repeatTime - 1) * incSeed", "array is too sort to do this");

            }

            for (var i = 0; i < repeatTime; i++)
            {
                var tmp_index = incSeed * i + start;                
                yield return selector(array[tmp_index], tmp_index); 
            }

        }

        static public IEnumerable<TResualt> Select<T, TResualt>(this T[] array, int start, int repeatTime, IndexedSelector<T, int, TResualt> selector)
        {
            return Select(array, start, repeatTime, 1, selector);
        }


        static public IEnumerable<TResualt> Select<T, TResualt>(this T[] array,  IndexedSelector<T, int, TResualt> selector)
        {
            return Select(array, 0, array.Length, 1, selector);
        }
    }
}
